﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using PlayingCards.Model.Entity;
using PlayingCards.Repository.BaseRepository;
using PlayingCards.Service.IEntityService;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace PlayingCards.Comm
{
    /// <summary>
    /// 服务扩展类
    /// </summary>
    public static class DataServiceExtension
    {
        /// <summary>
        ///  注入仓储
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddRepository(this IServiceCollection services)
        {
            services.AddScoped(typeof(BaseRepository<>));
            return services;
        }
        /// <summary>
        /// 注入业务层
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddDataService(this IServiceCollection services)
        {
            var baseType = typeof(IBase);  // 获取一个基类接口作为切入点
            var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;  // 获取当前域下的路径
            var referencedAssemblies = Directory.GetFiles(path, "*.dll").Select(Assembly.LoadFrom).ToArray(); // 获取该路径下的所有dll结尾的文件并加载为程序集
            // SelectMany 将所有程序集的定义类型合并成一个序列
            var types = referencedAssemblies.SelectMany(a => a.DefinedTypes)
                .Select(type => type.AsType())
                .Where(x => x != baseType && baseType.IsAssignableFrom(x)).ToArray();
            var implementTypes = types.Where(x => x.IsClass).ToArray();
            var interfaceTypes = types.Where(x => x.IsInterface).ToArray();
            foreach (var impIementType in implementTypes)
            {
                var interfaceType = interfaceTypes.FirstOrDefault(x => x.IsAssignableFrom(impIementType));
                if (interfaceType != null)
                {
                    services.AddScoped(interfaceType, impIementType);
                }
            }
            return services;
        }
        /// <summary>
        ///  注册SqlSugar
        /// </summary>
        /// <param name="services"></param>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public static IServiceCollection AddSqlSugar(this IServiceCollection services , string connectionString)
        {
            services.AddScoped<ISqlSugarClient>(s =>
            {
                var sqlSugar = new SqlSugarClient(new ConnectionConfig()
                {
                    DbType = DbType.SqlServer,
                    ConnectionString = connectionString,
                    IsAutoCloseConnection = true,
                },
                db =>
                {
                    db.Aop.OnLogExecuting = (sql, pars) =>
                    {
                        // 在这里可以记录 SQL 执行的日志等信息
                    };
                });
                return sqlSugar;
            });
            return services;
        }

        /// <summary>
        ///  映射模型
        /// </summary>
        /// <param name="services"></param>
        /// <param name="sqlSugar"></param>
        /// <returns></returns>
        public static IServiceCollection AddDetaEntity(this IServiceCollection services, ISqlSugarClient sqlSugar)
        {
            var baseType = typeof(BaseEntity); //获取基础类作为切入点
            // 获取动态程序库路径
            var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; // 获取当前域下的路径
            Type[] assembly = Assembly.LoadFrom(Path.Combine(path, "PlayingCards.Model.dll")) //获取该路径PlayingCards.Model 文件下的所有dll结尾的文件并加载为程序集
                .GetTypes()
                .Where(x => x != baseType && baseType.IsAssignableFrom(x))
                .ToArray();
            sqlSugar.DbMaintenance.CreateDatabase();
            //sqlSugar.CodeFirst.GetDifferenceTables(assembly); // 查询有差异的实体模型
            sqlSugar.CodeFirst.SetStringDefaultLength(200).InitTables(assembly);//根据types创建表
            return services;
        }

        /// <summary>
        ///  注入Jwt
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection AddJwt(this IServiceCollection services , IConfiguration configuration)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                // 取出私钥
                var key = Encoding.UTF8.GetBytes(configuration["JWTToken:SecurityKey"]);
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true, // 验证发布者
                    ValidIssuer = configuration["JWTToken:Issuer"],
                    ValidateAudience = true, // 验证接收者
                    ValidAudience = configuration["JWTToken:Audience"],
                    ValidateLifetime = true,// 验证是否过期
                    IssuerSigningKey = new SymmetricSecurityKey(key), // 验证私钥
                    RequireExpirationTime = true,
                    ValidateIssuerSigningKey = true,
                    ClockSkew = TimeSpan.Zero
                };
            });
            return services;
        }
        
    }
}
